package com.example.comm.socket;


/**
 * 服务端，随程序自启动，时刻监听端口发来的udp包。
 */

import com.example.comm.config.UdpConfig;
import com.example.comm.mqtt.MqttPushClient;
import com.example.comm.pojo.CarData;
import com.example.comm.utils.UDPDataHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.Filter;
import org.springframework.integration.annotation.Router;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.annotation.Transformer;
import org.springframework.integration.dsl.IntegrationFlow;
import org.springframework.integration.dsl.IntegrationFlows;
import org.springframework.integration.ip.dsl.Udp;
import org.springframework.messaging.handler.annotation.Headers;
import org.springframework.messaging.handler.annotation.Payload;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Map;


/**
 * UDP消息接收服务
 */
@Configuration
public class UdpServer {

    private static final Logger logger = LoggerFactory.getLogger(UdpServer.class);

    /**
     * UDP消息接收服务
     */
    @Bean
    public IntegrationFlow integrationFlow() {
        logger.info("UDP服务启动成功，端口号为: {}", UdpConfig.getListeningPort());
        return IntegrationFlows.from(Udp.inboundAdapter(UdpConfig.getListeningPort())).channel("udpChannel").get();
    }

    /**
     * 转换器,将从"udpChannel"通道的消息转换后发送到"udpFilter"通道
     */
    @Transformer(inputChannel = "udpChannel", outputChannel = "udpFilter")
    public String transformer(@Payload byte[] payload, @Headers Map<String, Object> headers) {

        //String message = new String(payload);将接收到的字节数组payload转换为字符串形式。
        String message = new String(payload);
        // todo 进行数据转换.
        //message = message.toUpperCase();将消息字符串转换为大写形式。这是一个简单的示例转换操作，你可以根据需要进行更复杂的数据转换操作。
        message = message.toUpperCase();

        System.out.println("接收到UDP信息 vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv" );


        return message;
    }

    /**
     * 过滤器，过滤掉不含VTG,GLL字符串的无用message。
     */
    @Filter(inputChannel = "udpFilter", outputChannel = "udpRouter")
    public boolean filter(String message, @Headers Map<String, Object> headers) {
//        // 获取来源Id
//        String id = headers.get("id").toString();
//        // 获取来源IP，可以进行IP过滤
//        String ip = headers.get("ip_address").toString();
//        // 获取来源Port
//        String port = headers.get("ip_port").toString();

        System.out.println("接收到UDP信息222222222222"+message);

        //是GPS数据
        if(message.contains("VTG") && message.contains("GLL") && message.contains("GGA")) {
            return true;
        } else {
            //是异常行为数据.因为UDP反复发数据，有重复几率，需要重复接收（后端无代码体现）
            if(message.contains("BELT")) {
                //是安全带信息，直接发走。添加时间数据，方便存储和判断重复
                SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                message += sdf.format(System.currentTimeMillis());
                System.out.println("安全带信息，后端发送的是" + message);

                UDPSend udpSend = new UDPSend();
                udpSend.sendMessage(message);
                return false;

            } else if(message.contains("左顾右盼")){
                //是左顾右盼，参考格式为2024-03-29 20:04:11 左顾右盼
                String mes1 = message.replace("左顾右盼","look");
                System.out.println("左顾右盼，后端发送的是" + mes1);

                UDPSend udpSend = new UDPSend();
                udpSend.sendMessage(mes1);
                return false;

            } else if(message.contains("mq3")) {
                //是酒驾数据
                SimpleDateFormat sdf= new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                message += sdf.format(System.currentTimeMillis());
                System.out.println("酒精数据，后端发送的是"+message);
                UDPSend udpSend = new UDPSend();
                udpSend.sendMessage(message);
                return false;


            } else {
                //是疲劳驾驶，包括打哈欠，瞌睡点头，眨眼，参考格式为2024-03-29 20:01:30 打瞌睡
                //因为发向北向的UDP无法解析中文，需要在此先替换成英文，在北向再次换成中文显示在仪表盘上
                String mes2 = "";
                if(message.contains("打哈欠"))
                {
                    mes2 = message.replace("打哈欠","yawn");
                } else if(message.contains("瞌睡点头")) {
                    mes2 = message.replace("瞌睡点头","sleep");
                } else {
                    mes2 = message.replace("眨眼","blink");
                }

                System.out.println("疲劳驾驶，后端发送的是" + mes2);

                UDPSend udpSend = new UDPSend();
                udpSend.sendMessage(mes2);
                return false;

            }





        }
    }

    /**
     * 路由分发处理器:可以进行分发消息被哪个处理器进行处理。此处让经过过滤器的信息传送给处理器1处理。
     */
    @Router(inputChannel = "udpRouter")
    public String router(String message, @Headers Map<String, Object> headers) {
        // 获取来源Id
        String id = headers.get("id").toString();
        // 获取来源IP，可以进行IP过滤
        String ip = headers.get("ip_address").toString();
        // 获取来源Port
        String port = headers.get("ip_port").toString();
        // todo 筛选，走那个处理器
//        if (true) {
            return "udpHandle1";
//        }
//        return "udpHandle2";
    }

    /**
     * 最终处理器1
     */
    @ServiceActivator(inputChannel = "udpHandle1")
    public void udpMessageHandle(String message) throws Exception {
        // todo 可以进行异步处理
//        logger.info("message在这里：" + message);

        //接收后进行处理，解析出速度VTG，经纬度GLL、G
        double v = 0;
        String lat_unfixed = "",lon_unfixed = "";   //未经处理的纬度，经度
        String NS = "未知" , EW = "未知2";
        double altitude = -10000; //未经处理的海拔高度

        //VTG-----------------------
        int findVTG = message.indexOf("VTG");
        if(findVTG == -1) logger.info("找不到字符串VTG");
        else {
            int prov = message.indexOf("N",findVTG);
            if(prov == -1) logger.info("找不到提示字符N");

            int aftv = message.indexOf(",K",findVTG);
            if(aftv == -1) logger.info("找不到提示字符K");

            if(prov > 0 && aftv >0) {
                String vString = message.substring(prov+2 , aftv);
                v = Double.parseDouble(vString);
                logger.info("小车速度为" + v);
            }

        }


        //GLL------------------------
        int findGLL = message.indexOf("GLL");
        if(findGLL == -1) logger.info("找不到字符串GLL");
        else {
            //查找纬度和纬度方向NS
            int findNS = message.indexOf("N",findGLL);
            if(findNS == -1) {
                findNS = message.indexOf("S",findGLL);
                if(findNS == -1) logger.info("找不到纬度方向NS");
            }

            NS = message.substring(findNS,findNS+1);

            lat_unfixed = message.substring(findGLL+4,findNS-1);

            //查找经度和经度方向EW
            int findEW = message.indexOf("E",findGLL);
            if(findEW == -1) {
                findEW = message.indexOf("S",findGLL);
                if(findEW == -1) logger.info("找不到经度方向EW");
            }

            EW = message.substring(findEW,findEW+1);

            if(findEW > 0 && findNS > 0) {
                lon_unfixed = message.substring(findNS+2,findEW-1);
            }
        }


        //GGA--------------------------
        int findGGA = message.indexOf("GGA");
        if(findGGA == -1) logger.info("找不到字符串GGA");
        else {
            int aftalt = message.indexOf(",M",findGGA);
            if(aftalt == -1) logger.info("找不到提示字符M");
            int proalt = 0;

            for(int i = aftalt - 1 ; i > 0; i --) {
                if(message.charAt(i) == ',') {
                    proalt = i;
                    break;
                }
            }

            if(proalt > 0 && aftalt > 0) {
                String altString = message.substring(proalt+1 , aftalt);
                altitude = Double.parseDouble(altString);
                logger.info("小车海拔高度为" + altitude);
            }
        }


//        System.out.println("处理前纬度为:"+lat_unfixed + "  纬度方向为:" + NS + "  处理前经度为:" + lon_unfixed + "经度方向为:" + EW);

        //处理为整数和小数部分
        int index1 = lat_unfixed.indexOf('.');
        String in_data3 = lat_unfixed.substring(0,index1);
        String in_data4 = lat_unfixed.substring(index1+1);

        int index3 = lon_unfixed.indexOf('.');
        String in_data1 = lon_unfixed.substring(0,index3);
        String in_data2 = lon_unfixed.substring(index3+1);

        ArrayList<Double> result =  UDPDataHandler.hander(in_data1,in_data2,in_data3,in_data4);
        if(result.get(0) == 0.0) System.out.println("目标不在国内");
        else System.out.println("处理后纬度为" + result.get(0) + "  经度为" + result.get(1));

        CarData carData = CarData.getInstance(result.get(0),result.get(1),v,altitude);
        String carDataSender = "lat:"+carData.getLat()+"lon" + carData.getLon() +"v:"+ carData.getSpeed() +"alt:"+ carData.getAltitude()+"end";

        //发送小车数据给另一服务器，141.28182 12.12121 3.1313
        MqttPushClient mqttPushClient = new MqttPushClient();
        mqttPushClient.publish("car_data",carDataSender);

    }

    /**
     * 最终处理器2
     */
    @ServiceActivator(inputChannel = "udpHandle2")
    public void udpMessageHandle2(String message) throws Exception {
        logger.info("UDP2:" + message);
    }
}
